package auth

import (
	"douhu_backend/internal/controller/common"
	"douhu_backend/internal/errors"
	authModel "douhu_backend/internal/model/auth"
	authService "douhu_backend/internal/services/auth"
	commonService "douhu_backend/internal/services/common"

	"github.com/kataras/iris/v12"
)

// AuthController 认证控制器
type AuthController struct {
	Base
	authService *authService.Service
}

// JWT 获取JWT服务（辅助方法）
func (c *AuthController) JWT() commonService.JWTService {
	return c.authService.JWT()
}

// NewAuthController 创建认证控制器实例
func NewAuthController(authService *authService.Service) *AuthController {
	return &AuthController{
		authService: authService,
	}
}

// SendCodeRequest 发送验证码请求参数
type SendCodeRequest struct {
	Phone string `json:"phone" validate:"required"`
	Typ   int    `json:"type" validate:"required"`
}

// LoginRequest 登录请求参数
type LoginRequest struct {
	Phone string `json:"phone" validate:"required"`
	Code  string `json:"code" validate:"required"`
}

// RegisterRequest 注册请求参数
type RegisterRequest struct {
	Phone string `json:"phone" validate:"required"`
	Code  string `json:"code" validate:"required"`
}

// UpdateProfileRequest 更新用户资料请求参数
type UpdateProfileRequest struct {
	Nickname string `json:"nickname"`
	Email    string `json:"email"`
	Birthday string `json:"birthday"` // 格式: YYYY-MM-DD
	Gender   int    `json:"gender"`
	Avatar   string `json:"avatar"`
}

// SendCode 发送短信验证码
// @Summary 发送短信验证码
// @Description 发送手机短信验证码，支持登录、注册、重置密码等场景
// @Tags 认证
// @Accept json
// @Produce json
// @Param request body SendCodeRequest true "发送验证码请求"
// @Success 200 {object} common.RspProto
// @Router /auth/send-code [post]
func (c *AuthController) SendCode(ctx iris.Context) {
	var req SendCodeRequest

	if err := ctx.ReadJSON(&req); err != nil {
		c.Error(ctx, ErrParams.Code, "请求参数解析失败", err)
		return
	}

	// 构建业务逻辑请求参数
	logicReq := &authService.SendSMSCodeRequest{
		Phone:    req.Phone,
		Typ:      req.Typ,
		ClientIP: c.GetClientIP(ctx),
	}

	// 调用业务逻辑
	err := c.authService.SendSMSCode(logicReq)
	if err != nil {
		// 判断是否为业务错误
		if serviceErr, ok := err.(*errors.ServiceError); ok {
			errno := c.mapServiceError(serviceErr)
			c.Error(ctx, errno.Code, errno.Message, nil)
			return
		}
		// 系统错误
		c.Error(ctx, ErrSystemError.Code, "系统错误", err)
		return
	}

	// 成功响应
	c.Success(ctx, map[string]interface{}{
		"message": "验证码发送成功",
	})
}

// Login 手机号验证码登录
// @Summary 手机号验证码登录
// @Description 使用手机号和短信验证码进行登录，支持自动注册
// @Tags 认证
// @Accept json
// @Produce json
// @Param request body LoginRequest true "登录请求"
// @Success 200 {object} common.RspProto
// @Router /auth/login [post]
func (c *AuthController) Login(ctx iris.Context) {
	var req LoginRequest

	if err := ctx.ReadJSON(&req); err != nil {
		c.Error(ctx, ErrParams.Code, "请求参数解析失败", err)
		return
	}

	// 构建业务逻辑请求参数
	logicReq := &authService.PhoneLoginRequest{
		Phone:    req.Phone,
		Code:     req.Code,
		ClientIP: c.GetClientIP(ctx),
	}

	// 调用业务逻辑
	loginData, err := c.authService.PhoneLogin(logicReq)
	if err != nil {
		// 判断是否为业务错误
		if serviceErr, ok := err.(*errors.ServiceError); ok {
			errno := c.mapServiceError(serviceErr)

			// 如果是登录锁定错误，需要返回额外数据
			if serviceErr.Code == errors.CodeLoginLocked && serviceErr.Data != nil {
				ctx.JSON(common.RspProto{
					Code:      errno.Code,
					Message:   errno.Message,
					Data:      serviceErr.Data,
					Error:     "",
					RequestID: ctx.Request().Header.Get("X-Request-Id"),
				})
				return
			}

			c.Error(ctx, errno.Code, errno.Message, nil)
			return
		}
		// 系统错误
		c.Error(ctx, ErrSystemError.Code, "系统错误", err)
		return
	}

	// 成功响应
	c.Success(ctx, map[string]interface{}{
		"access_token":       loginData.AccessToken,
		"refresh_token":      loginData.RefreshToken,
		"access_expires_at":  loginData.AccessExpiresAt,
		"refresh_expires_at": loginData.RefreshExpiresAt,
		"user": map[string]interface{}{
			"id":       loginData.User.ID,
			"phone":    loginData.User.Phone,
			"nickname": loginData.User.Nickname,
			"avatar":   loginData.User.Avatar,
			"status":   loginData.User.Status,
		},
	})
}

// RefreshTokenRequest 刷新Token请求参数
type RefreshTokenRequest struct {
	RefreshToken string `json:"refresh_token" validate:"required"`
}

// RefreshToken 刷新访问令牌
// @Summary 刷新访问令牌
// @Description 使用refresh token获取新的access token和refresh token
// @Tags 认证
// @Accept json
// @Produce json
// @Param request body RefreshTokenRequest true "刷新Token请求"
// @Success 200 {object} common.RspProto
// @Router /auth/refresh [post]
func (c *AuthController) RefreshToken(ctx iris.Context) {
	var req RefreshTokenRequest

	if err := ctx.ReadJSON(&req); err != nil {
		c.Error(ctx, ErrParams.Code, "请求参数解析失败", err)
		return
	}

	// 构建业务逻辑请求参数
	logicReq := &authService.RefreshTokenRequest{
		RefreshToken: req.RefreshToken,
	}

	// 调用业务逻辑
	tokenData, err := c.authService.RefreshAccessToken(logicReq)
	if err != nil {
		// 判断是否为业务错误
		if serviceErr, ok := err.(*errors.ServiceError); ok {
			errno := c.mapServiceError(serviceErr)
			c.Error(ctx, errno.Code, errno.Message, nil)
			return
		}
		// 系统错误
		c.Error(ctx, ErrSystemError.Code, "系统错误", err)
		return
	}

	// 成功响应
	c.Success(ctx, map[string]interface{}{
		"access_token":       tokenData.AccessToken,
		"refresh_token":      tokenData.RefreshToken,
		"access_expires_at":  tokenData.AccessExpiresAt,
		"refresh_expires_at": tokenData.RefreshExpiresAt,
	})
}

// GetUserInfo 获取当前用户信息
// @Summary 获取当前用户信息
// @Description 根据JWT token获取当前登录用户的基本信息
// @Tags 认证
// @Accept json
// @Produce json
// @Success 200 {object} common.RspProto
// @Router /auth/user [get]
func (c *AuthController) GetUserInfo(ctx iris.Context) {
	// 从上下文中获取用户信息（由认证中间件设置）
	userInterface := ctx.Values().Get("user")
	if userInterface == nil {
		c.Error(ctx, ErrNoAuth.Code, "用户未登录", nil)
		return
	}

	user, ok := userInterface.(*authModel.User)
	if !ok {
		c.Error(ctx, ErrSystemError.Code, "用户信息格式错误", nil)
		return
	}

	// 返回用户信息
	c.Success(ctx, map[string]interface{}{
		"user": map[string]interface{}{
			"id":              user.ID,
			"phone":           user.Phone,
			"username":        user.Username,
			"nickname":        user.Nickname,
			"avatar":          user.Avatar,
			"email":           user.Email,
			"birthday":        user.Birthday,
			"gender":          user.Gender,
			"login_type":      user.LoginType,
			"status":          user.Status,
			"last_login_time": user.LastLoginTime,
			"register_time":   user.RegisterTime,
		},
	})
}

// Register 手机号注册
// @Summary 手机号注册
// @Description 使用手机号和短信验证码进行注册
// @Tags 认证
// @Accept json
// @Produce json
// @Param request body RegisterRequest true "注册请求"
// @Success 200 {object} common.RspProto
// @Router /auth/register [post]
func (c *AuthController) Register(ctx iris.Context) {
	var req RegisterRequest

	if err := ctx.ReadJSON(&req); err != nil {
		c.Error(ctx, ErrParams.Code, "请求参数解析失败", err)
		return
	}

	// 构建业务逻辑请求参数
	logicReq := &authService.PhoneRegisterRequest{
		Phone:    req.Phone,
		Code:     req.Code,
		ClientIP: c.GetClientIP(ctx),
	}

	// 调用业务逻辑
	registerData, err := c.authService.PhoneRegister(logicReq)
	if err != nil {
		// 判断是否为业务错误
		if serviceErr, ok := err.(*errors.ServiceError); ok {
			errno := c.mapServiceError(serviceErr)
			c.Error(ctx, errno.Code, errno.Message, nil)
			return
		}
		// 系统错误
		c.Error(ctx, ErrSystemError.Code, "系统错误", err)
		return
	}

	// 成功响应
	c.Success(ctx, map[string]interface{}{
		"message": "注册成功，请登录",
		"user": map[string]interface{}{
			"id":       registerData.User.ID,
			"phone":    registerData.User.Phone,
			"nickname": registerData.User.Nickname,
		},
	})
}

// UpdateProfile 更新用户个人资料
// @Summary 更新用户个人资料
// @Description 更新当前登录用户的个人资料信息
// @Tags 认证
// @Accept json
// @Produce json
// @Param request body UpdateProfileRequest true "更新资料请求"
// @Success 200 {object} common.RspProto
// @Router /auth/profile [put]
func (c *AuthController) UpdateProfile(ctx iris.Context) {
	// 从上下文中获取用户信息（由认证中间件设置）
	userInterface := ctx.Values().Get("user")
	if userInterface == nil {
		c.Error(ctx, ErrNoAuth.Code, "用户未登录", nil)
		return
	}

	_, ok := userInterface.(*authModel.User)
	if !ok {
		c.Error(ctx, ErrSystemError.Code, "用户信息格式错误", nil)
		return
	}

	var req UpdateProfileRequest
	if err := ctx.ReadJSON(&req); err != nil {
		c.Error(ctx, ErrParams.Code, "请求参数解析失败", err)
		return
	}

	// TODO: 实现更新用户资料功能
	_ = req // 避免未使用变量错误
	c.Error(ctx, ErrSystemError.Code, "更新用户资料功能暂未实现", nil)
}
